package com.demo.chapter11future.asyncadddiscount;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.stream.Stream;
import com.demo.chapter11future.sync.Shop;

public class Demo2 {
	
	private static List<Shop> shops = Arrays.asList(new Shop("BestPrice"), new Shop("LetsSaveBig"), new Shop("MyFav"), new Shop("BuyAll"));
	private final Executor executor = Executors.newFixedThreadPool(Math.min(shops.size(), 100));
	
	
	public Stream<CompletableFuture<String>> findPriceStream(String product){
		return shops.stream()
			.map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice2(product), executor))
			.map(future -> future.thenApply(Quote::parse))
			.map(future -> future.thenCompose(quote -> CompletableFuture.supplyAsync(() -> Discount.applyDiscount(quote), executor)));
	}

	public static void main(String[] args) {
		Demo2 test = new Demo2();
        
		long start = System.nanoTime();
		//thenAccept只是在每个CompletableFuture上注册一个操作，该操作会在CompletableFuture完成执行后使用它的返回值
		Stream<CompletableFuture<Void>> voids = test.findPriceStream("iphone6s").map(f -> f.thenAccept(System.out::println));
		CompletableFuture[] futures = voids.toArray(size -> new CompletableFuture[size]);
		//allOf接受一个CompletableFuture构成的数组，数组中的所有对象都执行完毕后，返回一个CompletableFuture<Void>对象
		//所有对象都执行完毕后，调用join操作是个不错的主意
		CompletableFuture.allOf(futures).join();
		System.out.println("All shops have now responded in " + ((System.nanoTime() - start) / 1_000_000) + " msecs");
		
		long start2 = System.nanoTime();
		Stream<CompletableFuture<Void>> voids2 = test.findPriceStream("iphone6s").map(f -> f.thenAccept(System.out::println));
		CompletableFuture[] futures2 = voids2.toArray(size -> new CompletableFuture[size]);
		//anyOf任意一个执行完毕就会调用
		CompletableFuture.anyOf(futures2).join();
		System.out.println("anyOf shop have now responded in " + ((System.nanoTime() - start2) / 1_000_000) + " msecs");
        
	}

}
